<?php

/**
* alltosun.com 操作日志widget log.php
* ============================================================================
* 版权所有 (C) 2009-2012 北京互动阳光科技有限公司，并保留所有权利。
* 网站地址: http://www.alltosun.com
* ----------------------------------------------------------------------------
* 许可声明：这是一个开源程序，未经许可不得将本软件的整体或任何部分用于商业用途及再发布。
* ============================================================================
* $Author: 钱有明 (qianym@alltosun.com) $
* $Date: 2012-10-18 下午2:44:15 $
* $Id: log.php 25205 2013-04-24 06:38:13Z qianym $
*/

/**
 * 可以通过框架的观察者调用log  // 具体使用看观察者ModelResObserver
 */
class log_widget
{
    private $allow_action = array('create', 'updateBEF', 'update', 'delete');    // 允许的类型
    private $special_res  = array('task_relation', 'follower', 'file_relation'); // 一些关联表
    private $log_table        = 'log';                                           // 默认的log表
    private $log_detail_table = 'log_detail';                                    // 默认的log详情表
    private $action;                                                             // 当前操作类型
    private $table_name;                                                         // 表名
    private $key;                                                                // 主键
    private $key_id;                                                             // 主键的值
    private $table_status;                                                       // 数据表的相关信息
    private $table_columns;                                                      // 数据表结构的相关信息
    private $columns_comment;                                                    // 数据表中各字段的注释
    private $log_id;                                                             // 操作日志id
    private $op_id;                                                              // 当前操作人
    private $old_res_info;                                                       // 编辑前的信息

    /**
     * 记录操作日志
     * @param string $res_name
     * @param int $res_id
     * @param string $action
     * @return mixed 成功:$log_id 失败:false;
     * 使用访方法记log的前提是：表中有pk字段（同观察者）
     */
    public function record($res_name, $res_id, $action)
    {
        if (empty($res_name) || empty($res_id) || !in_array($action, $this->allow_action)) {
            return FALSE;
        }

        $this->op_id = user_helper::get_user_id();
        if (!$this->op_id) {
            return FALSE;
        }

        $this->key = _model($res_name)->pk();
        if (!$this->key) {
            return FALSE;
        }

        $this->table_name = $res_name;
        $this->key_id = $res_id;
        $this->action = $action;

        // 设置操作记录表
        $this->_set_log_table();

        // 表信息
        $this->table_status = _model($res_name)->getALL('show table status where name ="'.$res_name.'"');
        // 表结构
        $this->table_columns = _model($res_name)->getALL('show full columns from `'.$res_name.'`');
        foreach ($this->table_columns as $v) {
            $this->columns_comment[$v['Field']] = $v['Comment'];
        }

        if ($this->action != 'update') {
            // 操作日志，主表记录
            $this->_record_log_main();
        }

        //if ($this->action != 'updateBEF') {
            // 操作日志，详情记录
            $this->_record_log_detail();
        //}

        return $this->log_id;
    }

    /**
     * 记录主日志
     */
    private function _record_log_main()
    {
        $info = array(
                'company_id' => company_helper::get_company_id(),
                'op_id'      => $this->op_id,
                'res_name'   => $this->table_name,
                'res_id'     => $this->key_id,
                'action'     => $this->action,
                'comment'    => $this->table_status[0]['Comment']
        );
        $this->log_id = _model($this->log_table)->create($info);
    }

    /**
     * 记录操作变更详情
     */
    private function _record_log_detail()
    {
        //var_dump($this->action, $this->key_id);
        // 取出数据表中当前的信息
        $res_info = _model($this->table_name)->read($this->key_id);
        //var_dump($this->action, $this->table_name, $this->key_id, $this->log_id, $res_info);
        // 编辑前的操作(updateBEF)
        //debug_print_backtrace();
        if ($this->action == 'updateBEF') {
            $this->old_res_info = $res_info;
            return;
        }


        // 编辑操作
        if ($this->action == 'update') {
            if (!$this->log_id) {
                $current_log_info = _model($this->log_table)->read(array('op_id'=>$this->op_id, 'res_name'=>$this->table_name, 'res_id'=>$this->key_id, 'action'=>'updateBEF'), 'ORDER BY `id` DESC ');
                if (!$current_log_info) {
                    return FALSE;
                }

                $this->log_id = $current_log_info['id'];
            }
            if (!$this->log_id) {
                return FALSE;
            }

            _model($this->log_table)->update($this->log_id, array('action'=>'update'));

            $arr = array();
            foreach ($res_info as $k=>$v) {
                if ($this->old_res_info[$k] == $v) {
                    continue;
                }

                $detail_info = array(
                        'log_id'     => $this->log_id,
                        'field_name' => $k,
                        'old_value'  => $this->old_res_info[$k],
                        'new_value'  => $v,
                        'comment'    => $this->columns_comment[$k]
                );

                _model($this->log_detail_table)->create($detail_info);

                // 更新时间有变更，不算在log里
                if ($k == 'update_time') {
                    continue;
                }
                $arr[$k] = $v;
            }

            // 这个位置是对一些特殊资源的log做特殊处理，如：任务
            //var_dump($arr);
            $this->_fix_special_log($arr);

            // 新增操作，删除操作
        } else {
            foreach ($res_info as $k=>$v) {
                $detail_info = array(
                        'log_id'     => $this->log_id,
                        'field_name' => $k,
                        'old_value'  => '',
                        'new_value'  => $v,
                        'comment'    => $this->columns_comment[$k]
                );

                if ($this->action == 'delete') {
                    $detail_info['old_value'] = $v;
                    $detail_info['new_value'] = '';
                }

                _model($this->log_detail_table)->create($detail_info);
            }

            // 发一些有自增ID的资源的通知，邮件
            dispatch_helper::send($this->log_id);
        }
    }

    /**
     * 区分log存入哪张表中
     */
    private function _set_log_table()
    {
        if (in_array($this->table_name, log_config::$special_log_res)) {
            // 主log表
            $this->log_table = $this->table_name.'_log';
            // 详情表
            $this->log_detail_table = $this->table_name.'_log_detail';
        }
    }

    /**
     * @FIXME 这些为特殊需要提供的log
     * 一些特定的关联表的操作记录(例：相关任务、相关附件、相关人员)
     * @param string $action
     * @param array $params
     * @return int
     * @example follower(array('res_name'=>'task', 'res_id'=>$res_id, 'action'=>'create')
     */
    public function __call($action = '', $params = array())
    {
        //an_dump($action);exit;
        if (!is_array($params)) {
            return FALSE;
        }

        $params = $params[0];

        if (!isset($params['action']) || !in_array($params['action'], $this->allow_action)) {
            return FALSE;
        }
        if (!isset($params['res_name']) || empty($params['res_name'])) {
            return FALSE;
        }
        if (!isset($params['res_id']) || empty($params['res_id'])) {
            return FALSE;
        }

        $this->op_id = user_helper::get_user_id();
        if (!$this->op_id) {
            return FALSE;
        }
        $this->action = $params['action'];
        $this->table_name = $params['res_name'];
        $this->key_id = $params['res_id'];

        // 设置操作记录表
        $this->_set_log_table();

        // 表信息
        $this->table_status = _model($this->table_name)->getALL('show table status where name ="'.$this->table_name.'"');

        $info = array(
                'op_id'      => $this->op_id,
                'res_name'      => $this->table_name,
                'res_id'        => $this->key_id,
                'action'        => $this->action,
                'comment'       => $this->table_status[0]['Comment'],
                'real_res_name' => $action
        );

        // 提醒某人关注某资源
        if ($action == 'follower') {
            if (!isset($params['follower_ids']) || empty($params['follower_ids']) || !is_array($params['follower_ids'])) {
                return FALSE;
            }
            if (isset($params['assign'])) {
                $info['real_field'] = 'assign';
            }

            $info['difference'] = serialize($params['follower_ids']);

            // 在某资源中上传附件
        } elseif ($action == 'file_relation') {
            if (!isset($params['file_ids']) || empty($params['file_ids']) || !is_array($params['file_ids'])) {
                return FALSE;
            }

            $info['difference'] = serialize($params['file_ids']);
            // 某人上传了附件:附件名字  or 某人删除了附件:附件名字
            //$info['intro'] = user_helper::display_name($this->op_id);
            $info['intro'] = '';
            $info['intro'] .= log_config::$action[$params['action']].'了附件：'.display_title('file', $params['file_ids'][0]);

            // 添加任务关联
        } elseif ($action == 'task_relation') {
            if (!isset($params['task_ids']) || empty($params['task_ids']) || !is_array($params['task_ids'])) {
                return FALSE;
            }

            $info['difference'] = serialize($params['task_ids']);
            $info['intro'] = '';
            $info['intro'] .= log_config::$action[$params['action']].'子任务：'.display_title('task', $params['task_ids'][0]);

            // 添加了评论
        } elseif ($action == 'comment') {
            if (!isset($params['comment_ids']) || empty($params['comment_ids']) || !is_array($params['comment_ids'])) {
                return FALSE;
            }

            $info['difference'] = serialize($params['comment_ids']);
            $info['intro'] = '';
            $info['intro'] .= log_config::$action[$params['action']].'了评论 '.task_helper::strip_html(_uri('comment', $params['comment_ids'][0], 'content'), 30);

            // 协作
        } elseif ($action == 'cooperate') {
            if (!isset($params['cooperate_ids']) || empty($params['cooperate_ids']) || !is_array($params['cooperate_ids'])) {
                return FALSE;
            }

            $info['difference'] = serialize($params['cooperate_ids']);

            // 回收
        } elseif ($action == 'garbage') {
            if (!isset($params['garbage_ids']) || empty($params['garbage_ids']) || !is_array($params['garbage_ids'])) {
                return FALSE;
            }

            $info['difference'] = serialize($params['garbage_ids']);
            /* $info['intro'] = '';
            if ($params['action'] == 'create') {
                $info['intro'] .= '删除了';
            } else {
                $info['intro'] .= '还原了';
            }
            if (array_key_exists($info['res_name'], log_config::$log_res_relation)) {
                $info['intro'] .= log_config::$log_res_relation[$info['res_name']];
            } */

            // 收藏
        } elseif ($action == 'fav') {

        }

        $log_id = _model($this->log_table)->create($info);

        //@FIXME 发任务的邮件通知
        if ($this->table_name == 'task') {
            //task_helper::task_notice($log_id);
        }

        // 发一些操作关联表的通知(文件协作，关注， 文件回收等)
        dispatch_helper::send($log_id);

        return $log_id;
    }

    /**
     * @FIXME 这些为特殊需要提供的log
     * 对一些特殊资源的log，做特殊处理
     */
    private function _fix_special_log($arr)
    {
        if (empty($arr)) {
            return;
        }

        $log_info = _uri($this->log_table, $this->log_id);
        if (empty($log_info)) {
            return;
        }
        $intro = '';
        // field_name记录本次更改的字段，便于根据任务日志发通知（邮件，短信）
        $field_name = '';

        // 这个位置是对任务log的做特殊处理
        if ($this->table_name == 'task') {

            // 更改任务时间
            if (array_key_exists('start_time', $arr)) {
                $intro = '更改了任务时间';
                $field_name = 'start_time';
            } else if (array_key_exists('end_time', $arr)) {
                //$intro = user_helper::display_name($log_info['op_id']).'更改了任务时间';
                $intro = '更改了任务时间';
                $field_name = 'end_time';
                // 更改任务状态（确认，解决，打回等）
            } elseif (array_key_exists('task_status', $arr)) {
                $intro = task_config::$task_status_action[$arr['task_status']].'了任务';

                $field_name = 'task_status';
                // 转派任务
            } elseif (array_key_exists('assign_id', $arr)) {
                $intro = '转派任务给 <span style="color:green;">'.user_helper::display_name($arr['assign_id']).'</span>';

                $field_name = 'assign_id';
            } else if (array_key_exists('content', $arr)) {
                $intro = '更改了'.log_config::$log_res_relation[$this->table_name].'内容';

                $field_name = 'content';
            } else if (array_key_exists('group_id', $arr)) {
                $intro = '更改了'.log_config::$log_res_relation[$this->table_name].'项目';

                $field_name = 'group_id';
            }

            // 其它的
        } else if ($this->table_name == 'file') {
            if (array_key_exists('version_id', $arr)) {
                $intro = '上传新文件，生成了版本 '.file_helper::get_version_order($arr['version_id']);

                $field_name = 'version_id';
            }
        } else if ($this->table_name == 'work') {
            if (array_key_exists('work_status', $arr)) {
                $field_name = 'work_status';
            } else if (array_key_exists('work_time', $arr) && count($arr) == 1) {
                $field_name = 'work_time';
            } else if (array_key_exists('content', $arr) && count($arr) == 1) {
                $field_name = 'content';
            }
        } else if ($this->table_name == 'attendance') {
            if (array_key_exists('attendance_status', $arr)) {
                $field_name = 'attendance_status';
            } else if (array_key_exists('start_time', $arr) && count($arr) == 1) {
                $field_name = 'content';
            } else if (array_key_exists('content', $arr) && count($arr) == 1) {
                $field_name = 'content';
            }
        }

        if (array_key_exists('title', $arr)) {
            //$intro = '更改'.log_config::$log_res_relation[$this->table_name].'名字为： '.$arr['title'];

            $field_name = 'title';
        } else if (array_key_exists('status', $arr)) {
            if ($arr['status'] == 1) {
                $intro = '从回收站还原了 '.log_config::$log_res_relation[$this->table_name].display_title($log_info['res_name'], $log_info['res_id']);
            } else if ($arr['status'] == 0) {
                $intro = '删除了 '.log_config::$log_res_relation[$this->table_name].display_title($log_info['res_name'], $log_info['res_id']);
            }

            $field_name = 'status';
        }

        if (empty($field_name)) {
            return;
        }

        _model($this->log_table)->update($this->log_id, array('intro'=>$intro, 'real_field'=>$field_name));

        // 发一些有自增id的资源的编辑操作的通知
        dispatch_helper::send($this->log_id);
    }

    /**
     * 取得某条日志信息
     * @param array $params
     * @return array
     */
    public function get_log_info($params)
    {
        if (empty($params) || !is_array($params)) {
            return array();
        }

        return _uri('log', $params);
    }

    /**
     * 取得操作日志列表
     * @param array $params
     * @return array
     */
    public function get_list($params)
    {
        if (empty($params) || !is_array($params)) {
            return array();
        }

        $page = Request::getParam('page_no', 1);
        $per_page = 30;

        $filter = array();
        if (isset($params['op_id']) && !empty($params['op_id'])) {
            $filter['op_id'] = $params['op_id'];
        }
        if (isset($params['res_name']) && !empty($params['res_name'])) {
            $filter['res_name'] = $params['res_name'];
        }
        if (isset($params['res_id']) && !empty($params['res_id'])) {
            $filter['res_id'] = $params['res_id'];
        }
        if (isset($params['start_time']) && !empty($params['start_time'])) {
            $filter['add_time >='] = $params['start_time'].' 00:00:00';
        }
        if (isset($params['end_time']) && !empty($params['end_time'])) {
            $filter['add_time <='] = $params['end_time'].' 23:59:59';
        }
        if (empty($filter)) {
            return array();
        }

        $count = _model('log')->getTotal($filter);
        $log_list = array();
        if ($count) {
            $pager = new Pager($per_page);
            //an_dump($filter);
            $log_list = _model('log')->getList($filter, 'ORDER BY `id` DESC '.$pager->getLimit($page));
            foreach ($log_list as $k=>$v) {
                $info = log_helper::generate_log_info($v['id']);
                $log_list[$k]['intro'] = $info;
            }

            if ($pager->generate($count)) {
                Response::assign('pager', $pager);
            }
        }

        return $log_list;
    }

    /**
     * 取得通用操作日志的详情
     */
    public function get_log_detail_list($log_id)
    {
        return _model('log_detail')->getList(array('log_id'=>$log_id), 'ORDER BY `id` DESC');
    }
}
?>